package com.sservice.service.utils.wx_third_platform;

import com.alibaba.fastjson.JSONObject;
import com.sservice.common.Constants;
import com.sservice.service.common.AdvancedUtil;
import com.sservice.service.service.IComService;
import com.sservice.service.service.redis.Redis;
import com.sservice.urp.entity.Com;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by suweiming on 2018/8/20.
 */
@Component
public class RequestUtil {

    private static Logger logger = LoggerFactory.getLogger(RequestUtil.class);
    @Autowired
    AdvancedUtil advancedUtil;
    @Autowired
    IComService iComService;

    /**
     * 访问token
     *
     * @return
     * @throws IOException
     */
    public JSONObject requestToken() throws IOException {
        Map map = new HashMap();
        map.put("component_appid", Constants.componentAppId);
        map.put("component_appsecret", Constants.componentAppSecret);
        map.put("component_verify_ticket", Redis.get(Constants.KEY_COMPONENT_VERIFY_TICKET));
        JSONObject userInfo = postRequest(UrlUtils.thirdPlatFormGetToken(), map);
        if("40013".equals(userInfo.getString("errCode"))){
            return userInfo;
        }
        logger.debug("requestToken: " + userInfo);
        logger.debug("requestToken: " + userInfo.getString("component_access_token"));
        String token = userInfo.getString("component_access_token");
        if (token == null) {
            token = "";
        }
        Redis.set(Constants.KEY_THIRD_PLATFORM_ACCESS_TOKEN, token.replaceAll("\"", ""));
        Redis.expire(Constants.KEY_THIRD_PLATFORM_ACCESS_TOKEN,
                userInfo.getInteger("expires_in") - 60 * 2);
        return userInfo;
    }

    /**
     * 获取预授权码
     *
     * @return
     * @throws IOException
     */
    public JSONObject requestPreAuthCode() throws IOException {
        Map map = new HashMap();
        map.put("component_appid", Constants.componentAppId);
        String thirdAccessToken = getComponentAccessTokenStr();
        JSONObject userInfo = postRequest(UrlUtils.thirdPlatFormGetPreAuthCode(thirdAccessToken), map);
        Redis.set(Constants.KEY_PRE_AUTH_CODE, userInfo.getString("pre_auth_code").replaceAll("\"", ""));
        Redis.expire(Constants.KEY_PRE_AUTH_CODE,
                userInfo.getInteger("expires_in") - 30);
        return userInfo;
    }

    /**
     * 通过授权码获取第三方调用凭据
     *
     * @return
     * @throws IOException
     */
    public JSONObject requestApiTicketByAuthCode(String authCode) throws IOException {
        Map map = new HashMap();
        map.put("component_appid", Constants.componentAppId);
        map.put("authorization_code", authCode);
        String accesstoken = getComponentAccessTokenStr();
        JSONObject userInfo = postRequest(UrlUtils.getTicketByAuthCode(accesstoken), map);
        logger.debug("======>>>>=====" + userInfo.getString("authorization_info"));
        userInfo = JSONObject.parseObject(userInfo.getString("authorization_info"));
        String AUTH_APPID = userInfo.getString("authorizer_appid").replaceAll("\"", "");
        Redis.set(Constants.KEY_PRE_AUTH_CODE + "authorizer_appid" + AUTH_APPID, AUTH_APPID);
        Redis.set(Constants.KEY_PRE_AUTH_CODE + "authorizer_access_token" + AUTH_APPID, userInfo.getString("authorizer_access_token").replaceAll("\"", ""));
        Redis.set(Constants.KEY_PRE_AUTH_CODE + "authorizer_refresh_token" + AUTH_APPID, userInfo.getString("authorizer_refresh_token").replaceAll("\"", ""));
        Redis.expire(Constants.KEY_PRE_AUTH_CODE + "authorizer_access_token" + AUTH_APPID,
                userInfo.getInteger("expires_in") - 120);//最后两分钟
        return userInfo;
    }

    public String getApiToken(String sysId) throws IOException {
        Com sy = iComService.selectByPrimaryKey(Integer.valueOf(sysId));
        if (sy.getAppId() == null || "".equals(sy.getAppId())) { //公众号未对第三方平台未授权
            throw new RuntimeException("api authorize not exist");
        }
        String authorizer_access_token = Redis.get(Constants.KEY_PRE_AUTH_CODE + "authorizer_access_token" + sy.getAppId());
        logger.debug(Constants.KEY_PRE_AUTH_CODE + "authorizer_access_token" + sy.getAppId());
        logger.debug(authorizer_access_token);
        if ("".equals(authorizer_access_token) || authorizer_access_token == null) {
            logger.debug("过期刷新");
            logger.debug(Constants.KEY_PRE_AUTH_CODE + "authorizer_refresh_token" + sy.getAppId());
            String authorizer_refresh_token = Redis.get(Constants.KEY_PRE_AUTH_CODE + "authorizer_refresh_token" + sy.getAppId());
            logger.debug(authorizer_refresh_token);
            if (!"".equals(authorizer_refresh_token) && authorizer_refresh_token != null) {
                refreshApiTicketBy(sy.getAppId());
                authorizer_access_token = Redis.get(Constants.KEY_PRE_AUTH_CODE + "authorizer_access_token" + sy.getAppId());
            } else {
                throw new RuntimeException("authorizer_refresh_token is not exist");
            }
        }

        return authorizer_access_token;

    }


    /**
     * 刷新第三方token
     *
     * @return
     * @throws IOException
     */
    public JSONObject refreshApiTicketBy(String appId) throws IOException {
        Map map = new HashMap();
        logger.debug("刷新-----");
        map.put("component_appid", Constants.componentAppId);
        String authorizer_refresh_token = Redis.get(Constants.KEY_PRE_AUTH_CODE + "authorizer_refresh_token" + appId);
        logger.debug(authorizer_refresh_token);
        map.put("authorizer_refresh_token", authorizer_refresh_token);
        map.put("authorizer_appid", appId);
        logger.debug("=========KEY_THIRD_PLATFORM_ACCESS_TOKEN======");
        String thirdPlatformAccessToken = getComponentAccessTokenStr();
        logger.debug(thirdPlatformAccessToken);
        logger.debug(thirdPlatformAccessToken);

        JSONObject userInfo = this.postRequest(UrlUtils.getRefreshTicketBy(thirdPlatformAccessToken), map);
        logger.debug(userInfo.toJSONString());
        Redis.set(Constants.KEY_PRE_AUTH_CODE + "authorizer_access_token" + appId, userInfo.getString("authorizer_access_token").replaceAll("\"", ""));
        Redis.set(Constants.KEY_PRE_AUTH_CODE + "authorizer_refresh_token" + appId, userInfo.getString("authorizer_refresh_token").replaceAll("\"", ""));
        Redis.expire(Constants.KEY_PRE_AUTH_CODE + "authorizer_access_token" + appId,
                userInfo.getInteger("expires_in") - 120);
        return userInfo;
    }


    public JSONObject getAuthorizer(String authorizerAppid) throws IOException {
        Map map = new HashMap();
        map.put("component_appid", Constants.componentAppId);
        map.put("authorizer_appid", authorizerAppid);

        JSONObject userInfo = this.postRequest(UrlUtils.getRefreshTicketBy(getComponentAccessTokenStr()), map);
        userInfo = JSONObject.parseObject(userInfo.getString("authorizer_info"));

        return userInfo;
    }

    public String getUserInfo(String accessToken, String openid) {
        String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openid + "&lang=zh_CN";
        //getRequest(url);
        return null;
    }

    public String[] getAccessTokenByCode(String code, String authorizerAppid) throws IOException {
//        if (!com.sservice.common.StringUtils.isBlank(Redis.get("access_token" + authorizerAppid))) {
//            return new String[]{Redis.get("access_token" + authorizerAppid)};
//        }
//        if (!com.sservice.common.StringUtils.isBlank(Redis.get("refresh_token" + authorizerAppid))) {//
//            refreshAccessToken(Redis.get("refresh_token" + authorizerAppid), authorizerAppid);
//            return new String[]{Redis.get("access_token" + authorizerAppid)};
//        }
        String url = getAccessTokenByCode1(code, authorizerAppid);
        logger.debug(url);
        JSONObject userInfo = getRequest(url);
        logger.debug(userInfo.toJSONString());
        Redis.set("access_token" + authorizerAppid, userInfo.getString("access_token"));
        Redis.expire("access_token" + authorizerAppid, userInfo.getInteger("expires_in") - 5 * 60);
        Redis.set("refresh_token" + authorizerAppid, userInfo.getString("refresh_token"));
        Redis.expire("refresh_token" + authorizerAppid, 30 * 24 * 60 * 60);
        //Redis.expire("openid" + authorizerAppid, 30 * 24 * 60 * 60);

        Redis.set("scope" + authorizerAppid, userInfo.getString("scope"));
        return new String[]{userInfo.getString("access_token"), userInfo.getString("openid")};
    }

    public String getAccessTokenByCode1(String code, String appId) throws IOException {
        String componentAccessToken = getComponentAccessTokenStr();
        return String.format("https://api.weixin.qq.com/sns/oauth2/component/access_token?appid=%s&code=%s&grant_type=authorization_code&component_appid=%s&component_access_token=%s",
                appId, code, Constants.componentAppId, componentAccessToken

        );
    }

    /**
     * 统一获取第三方访问token 方法，如果已过期，则自动刷新
     *
     * @return
     */
    public String getComponentAccessTokenStr() {
        String thirdPlatformAccessToken = Redis.get(Constants.KEY_THIRD_PLATFORM_ACCESS_TOKEN);
        logger.debug(thirdPlatformAccessToken);
        if (StringUtils.isBlank(thirdPlatformAccessToken)) {
            try {
                requestToken();
            } catch (IOException e) {
                e.printStackTrace();
            }
            thirdPlatformAccessToken = Redis.get(Constants.KEY_THIRD_PLATFORM_ACCESS_TOKEN);
        }
        return thirdPlatformAccessToken;
    }

    /**
     * 刷新访问token
     *
     * @param authorizerAppid
     * @throws IOException
     */
    public void refreshAccessToken(String authorizerAppid) throws IOException {
        String refreshToken = Redis.get("refresh_token" + authorizerAppid);

        JSONObject userInfo = getRequest(getRefreshAccessToken(refreshToken, authorizerAppid));
        Redis.set("access_token" + authorizerAppid, userInfo.getString("access_token"));
        Redis.expire("access_token" + authorizerAppid, userInfo.getInteger("expires_in") - 5 * 60);
        Redis.set("refresh_token" + authorizerAppid, userInfo.getString("refresh_token"));
        Redis.expire("refresh_token" + authorizerAppid, 30 * 24 * 60 * 60);

        Redis.set("scope" + authorizerAppid, userInfo.getString("scope"));
    }

    public String getRefreshAccessToken(String refreshToken, String appId) throws IOException {
        String componentAccessToken = getComponentAccessTokenStr();
        return String.format("https://api.weixin.qq.com/sns/oauth2/component/refresh_token?appid=%s&grant_type=refresh_token&component_appid=%s&component_access_token=%s&refresh_token=%s",
                appId, Constants.componentAppId, componentAccessToken, refreshToken

        );
    }

    /**
     * get 请求
     *
     * @param url
     * @return
     * @throws IOException
     */
    public JSONObject getRequest(String url) throws IOException {
        return advancedUtil.httpsRequest(url, "GET", null);
    }

    /**
     * post 请求
     *
     * @param url
     * @param param
     * @return
     * @throws IOException
     */

    public JSONObject postRequest(String url, Object param) throws IOException {

        return advancedUtil.httpsRequest(url, "POST", JSONObject.toJSONString(param));

    }
}
